import abc
from abc import ABC
from prettytable import PrettyTable
import sympy


class Logic:
    @abc.abstractmethod
    def value(self):
        pass


class Predict(Logic, ABC):

    def __init__(self, left: Logic, right: Logic):
        self.left = left
        self.right = right


class TrueValue(Logic):
    def value(self):
        return True


class FalseValue(Logic):
    def value(self):
        return False


class Not(Logic):

    def __init__(self, target: Logic):
        self.target = target

    def value(self):
        return not self.target.value()

    @staticmethod
    def get_truth_table():
        truth_table = PrettyTable()
        truth_table.field_names = ['P', '¬P']
        truth_table.add_row(['True', 'False'])
        truth_table.add_row(['False', 'True'])
        return truth_table


class And(Predict):

    def value(self):
        return self.left.value() and self.right.value()

    @staticmethod
    def get_truth_table():
        truth_table = PrettyTable()
        truth_table.field_names = ['P', 'Q', 'P ∧ Q']
        truth_table.add_row(['F', 'F', 'F'])
        truth_table.add_row(['F', 'T', 'F'])
        truth_table.add_row(['T', 'F', 'F'])
        truth_table.add_row(['T', 'T', 'T'])
        return truth_table


class Or(Predict):

    def value(self):
        return self.left.value() or self.right.value()

    @staticmethod
    def get_truth_table():
        truth_table = PrettyTable()
        truth_table.field_names = ['P', 'Q', 'P ∨ Q']
        truth_table.add_row(['F', 'F', 'F'])
        truth_table.add_row(['F', 'T', 'T'])
        truth_table.add_row(['T', 'F', 'T'])
        truth_table.add_row(['T', 'T', 'T'])
        return truth_table

